/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.bice.backbean;

import com.bice.controller.entity.BiceUser;
import com.bice.util.FacesUtil;
import com.bice.util.annotation.SessionResource;
import com.bice.util.annotation.SessionUserResource;
import com.bice.util.annotation.SpringServiceResource;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

/**
 *
 * @author Sirius
 */
public class BackBean implements Serializable {

    public static final String SESSION_BEAN = "sessionBean";
    public static final String SESSION_BEAN_USER = "user";
    
    /**
     * Create an instance of Back bean
     */
    public BackBean() {
        initResources();
    }
    
    private void initResources() {
        Field[] fields = getClass().getDeclaredFields();
        for(Field i : fields) {
            //Load spring services
            if(i.getAnnotation(SpringServiceResource.class) != null) {
                boolean accesible = i.isAccessible();
                i.setAccessible(true);
                try {
                    i.set(this, getSpringBean(i.getType()));
                } catch(Exception ex) {
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Can not inject: " + i.getType().getCanonicalName(), ex);
                }
                i.setAccessible(accesible);
            }
            //Load sessions
            else if(i.getAnnotation(SessionResource.class) != null && i.getType().equals(SessionBean.class)){
                boolean accesible = i.isAccessible();
                i.setAccessible(true);
                try {
                    i.set(this, getSessionBean());
                } catch(Exception ex) {
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Can not inject: " + i.getType().getCanonicalName(), ex);
                }
                i.setAccessible(accesible);
            }
            //Load session user
            else if(i.getAnnotation(SessionUserResource.class) != null && i.getType().equals(BiceUser.class) && 
                    getSessionBean() != null && getSessionBean().getUser() != null) {
                boolean accesible = i.isAccessible();
                i.setAccessible(true);
                try {
                    i.set(this, getSessionBean().getUser());
                } catch(Exception ex) {
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Can not inject: " + i.getType().getCanonicalName(), ex);
                }
                i.setAccessible(accesible);
            }
        }
    }

    /**
     * Get EL context value
     * @param bean Bean to get
     * @param property Property to get from bean
     * @return Value of property
     */
    public Object getELValue(String bean, String property) {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().evaluateExpressionGet(context, String.format("#{%s.%s}", bean, property), Object.class);
    }

    /**
     * Encrypt an string
     * @param value Value to encrypt
     * @return Value encripted
     */
    public String encrypt(String value) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(BackBean.class.getName()).log(Level.SEVERE, null, ex);
            while(value.length() < 32) {
                value += value;
            }
            if(value.length() >= 32){
                value = value.substring(0, 32);
            }
            return value;
        }
        byte[] b = md.digest(value.getBytes());
        int size = b.length;
        StringBuilder h = new StringBuilder(size);
        for (int i = 0; i < size; i++) {
            int u = b[i] & 255;
            if (u < 16) {
                h.append("0").append(Integer.toHexString(u));
            } else {
                h.append(Integer.toHexString(u));
            }
        }
        return h.toString();
    }

    /**
     * @return The session bean
     */
    protected SessionBean getSessionBean() {
        return (SessionBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(SESSION_BEAN);
    }
    
    /**
     * @param clazz of bean
     * @return The bean of class
     */
    public Object getSpringBean(Class clazz) {
        if(clazz != null) {
            ServletContext context = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
            String name = clazz.getSimpleName();
            name = name.substring(0, 1).toLowerCase() + name.substring(1);
            return FacesUtil.getSpringBean(context, name);
        }
        return null;
    }
    //</editor-fold>
    
    /**
     * Get root path to navigate
     * @return Relative path including faces context
     */
    public String getRootPath() {
        String path = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
        if(!path.contains("faces")) {
            path = "/faces";
        } else {
            path = "";
        }
        return path;
    }

}